/* /% C %/ */
/***********************************************************************
 * cint (C/C++ interpreter)
 ************************************************************************
 * Source file bc_inst.cxx
 ************************************************************************
 * Description:
 *  bytecode instruction generator
 ************************************************************************
 * Copyright(c) 2004~2004  Masaharu Goto 
 *
 * Permission to use, copy, modify and distribute this software and its 
 * documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  The author makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 ************************************************************************/

#include "bc_inst.h"
#include "Api.h"
#include "Property.h"

int G__bc_compile_function(struct G__ifunc_table *ifunc,int iexist);

////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// LD_IFUNC optimization
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
extern "C" int G__LD_IFUNC_optimize(struct G__ifunc_table* ifunc,int ifn
				   ,long * /*inst*/,int pc) {
  G__MethodInfo m;
  m.Init((long)ifunc,ifn,(G__ClassInfo*)NULL);

  if((m.Property()&(G__BIT_ISCOMPILED|G__BIT_ISBYTECODE))==0) {
    // if this is bare interpreted function, compile as bytecode
    G__bc_compile_function(ifunc,ifn);
  }

  if(m.Property()&G__BIT_ISCOMPILED) {
#ifdef G__ASM_DBG
    if(G__asm_dbg) G__fprinterr(G__serr,"call compiled function\n");
#endif	
    G__asm_inst[pc] = G__LD_FUNC;
    G__asm_inst[pc+1] = (long)m.Name();
    // preserve hash:2 and paran:3
    G__asm_inst[pc+4] = (long)m.InterfaceMethod();
    G__asm_inst[pc+5] = G__JMP;
    G__asm_inst[pc+6] = pc+8;
    G__asm_inst[pc+7] = G__NOP;
    return(1);
  }
  else if(m.Property()&G__BIT_ISBYTECODE) {
#ifdef G__ASM_DBG
    if(G__asm_dbg) G__fprinterr(G__serr,"call G__exec_bytecode optimized\n");
#endif	
    G__asm_inst[pc] = G__LD_FUNC;
    G__asm_inst[pc+1] = (long)m.GetBytecode();
    // preserve hash:2 and paran:3
    G__asm_inst[pc+4] = (long)G__exec_bytecode;
    G__asm_inst[pc+5] = G__JMP;
    G__asm_inst[pc+6] = pc+8;
    G__asm_inst[pc+7] = G__NOP;
    return(1);
  }
  return(0);
}

////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// G__bc_inst class
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
int G__bc_inst::inc_cp_asm(int cp_inc,int dt_dec)
{
  G__asm_cp+=cp_inc;
  G__asm_dt-=dt_dec;

  if(G__asm_instsize && G__asm_cp>G__asm_instsize-8) {
    G__asm_instsize += 0x100;
    void *p = realloc((void*)G__asm_stack,sizeof(long)*G__asm_instsize);
    if(!p) G__genericerror("Error: memory exhausted for bytecode instruction buffer\n");
    G__asm_inst = (long*)p;
  }
  else if(!G__asm_instsize && G__asm_cp>G__MAXINST-8) {
    if(G__asm_dbg) {
      G__fprinterr(G__serr,"Warning: loop compile instruction overflow");
      G__printlinenum();
    }
    G__abortbytecode();
  }

  if(G__asm_dt<30) {
    if(G__asm_dbg) {
      G__fprinterr(G__serr,"Warning: loop compile data overflow");
      G__printlinenum();
    }
    G__abortbytecode();
  }
  return(0);
}

////////////////////////////////////////////////////////////////////////////
// optimizer
////////////////////////////////////////////////////////////////////////////
void G__bc_inst::optimizeloop(int start,int /* end */) {
  G__asm_inst[G__asm_cp]=G__RETURN;
  G__asm_optimize(&start); // legacy
}
////////////////////////////////////////////////////////////////////////////
void G__bc_inst::optimize(int start,int /* end */) {
  G__asm_inst[G__asm_cp]=G__RETURN;
  G__asm_optimize3(&start); // legacy
}


////////////////////////////////////////////////////////////////////////////
// instruction generator
////////////////////////////////////////////////////////////////////////////
#ifdef G__NEVER
// Generated by optimizer, no need to generate in compiler
void G__bc_inst::LDST_VAR_P();
void G__bc_inst::LDST_LVAR_P();
void G__bc_inst::LDST_MVAR_P();
void G__bc_inst::LDST_VAR_INDEX();
void G__bc_inst::LDST_VAR_INDEX_OPR();
void G__bc_inst::OP2_OPTIMIZED();
void G__bc_inst::OP1_OPTIMIZED();
//
void G__bc_inst::CMPJMP();
#endif

/**************************************************************************
* LD
**************************************************************************/
void G__bc_inst::LD(G__value *pval) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: LD %ld from %x\n"
			       ,G__asm_cp,G__int(*pval)
			       ,G__asm_dt);
#endif
  G__asm_inst[G__asm_cp]=G__LD;
  G__asm_inst[G__asm_cp+1]=G__asm_dt;
  G__asm_stack[G__asm_dt] = *pval;
  inc_cp_asm(2,1);
}

/**************************************************************************
* LD
**************************************************************************/
void G__bc_inst::LD(int a) {
  G__value val;
  val.obj.d = 0.0;
  G__letint(&val,'i',(long)a);
  val.isconst=G__CONSTVAR;
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: LD %ld from %x\n"
			       ,G__asm_cp,G__int(val)
			       ,G__asm_dt);
#endif
  G__asm_inst[G__asm_cp]=G__LD;
  G__asm_inst[G__asm_cp+1]=G__asm_dt;
  G__asm_stack[G__asm_dt] = val;
  inc_cp_asm(2,1);
}

/**************************************************************************
* CL
**************************************************************************/
void G__bc_inst::CL() {
  G__asm_clear(); // legacy
}

/**************************************************************************
* OP2
**************************************************************************/
void G__bc_inst::OP2(int opr) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) {
      if(isprint(opr)) 
	  G__fprinterr(G__serr,"%3x: OP2  '%c' %d\n"
		       ,G__asm_cp,opr,opr);
      else
	  G__fprinterr(G__serr,"%3x: OP2  %d\n"
		       ,G__asm_cp,opr);
  }
#endif
  G__asm_inst[G__asm_cp]=G__OP2;
  G__asm_inst[G__asm_cp+1]=opr;
  inc_cp_asm(2,0);
}

/**************************************************************************
* CNDJMP
**************************************************************************/
int G__bc_inst::CNDJMP(int addr) {
  int asm_jumppointer=0;
  if(addr) {
#ifdef G__ASM_DBG
    if(G__asm_dbg) G__fprinterr(G__serr,"%3x: CNDJMP %d to %x\n"
			       ,G__asm_cp
				,G__int(G__asm_stack[G__asm_dt-1])
			       ,G__asm_inst[G__asm_cp+1]);
#endif
    G__asm_inst[G__asm_cp]=G__CNDJMP;
    G__asm_inst[G__asm_cp+1]=addr;
    inc_cp_asm(2,0);
  }
  else {
#ifdef G__ASM_DBG
    if(G__asm_dbg) 
      G__fprinterr(G__serr,"%3x: CNDJMP assigned later\n",G__asm_cp);
#endif
    G__asm_inst[G__asm_cp]=G__CNDJMP;
    G__asm_inst[G__asm_cp+1]=0;
    asm_jumppointer = G__asm_cp+1;
    inc_cp_asm(2,0);
  }
  return(asm_jumppointer);
}

/**************************************************************************
* JMP
**************************************************************************/
int G__bc_inst::JMP(int addr) {
  int asm_jumppointer=0;
  if(addr) {
#ifdef G__ASM_DBG
    if(G__asm_dbg) G__fprinterr(G__serr,"%3x: JMP to %x\n"
			       ,G__asm_cp
				,G__asm_inst[G__asm_cp+1]);
#endif
    G__asm_inst[G__asm_cp]=G__JMP;
    G__asm_inst[G__asm_cp+1]=addr;
    inc_cp_asm(2,0);
  }
  else {
#ifdef G__ASM_DBG
    if(G__asm_dbg) 
      G__fprinterr(G__serr,"%3x: JMP assigned later\n",G__asm_cp);
#endif
    G__asm_inst[G__asm_cp]=G__JMP;
    G__asm_inst[G__asm_cp+1]=0;
    asm_jumppointer = G__asm_cp+1;
    inc_cp_asm(2,0);
  }
  return(asm_jumppointer);
}

/**************************************************************************
* POP
**************************************************************************/
void G__bc_inst::POP() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: POP\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__POP;
  inc_cp_asm(1,0);
}

/**************************************************************************
* LD_FUNC
**************************************************************************/
void G__bc_inst::LD_FUNC(const char* funcname,int hash,int paran,void* pfunc) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,
			      "%3x: LD_FUNC compiled %s paran=%d\n"
			      ,G__asm_cp,funcname,paran);
#endif
  if(!hash) {
    int len;
    G__hash(funcname,hash,len);
  }
  G__asm_inst[G__asm_cp]=G__LD_FUNC;
  G__asm_inst[G__asm_cp+1] = (long)(&G__asm_name[G__asm_name_p]);
  G__asm_inst[G__asm_cp+2]=hash;
  G__asm_inst[G__asm_cp+3]=paran;
  G__asm_inst[G__asm_cp+4]=(long)pfunc;
  if(G__asm_name_p+strlen(funcname)+1<G__ASM_FUNCNAMEBUF) {
    strcpy(G__asm_name+G__asm_name_p,funcname);
    G__asm_name_p += strlen(funcname)+1;
    inc_cp_asm(5,0);
  }
  else {
    G__abortbytecode();
#ifdef G__ASM_DBG
    if(G__asm_dbg) {
	G__fprinterr(G__serr,"COMPILE ABORT function name buffer overflow");
	G__printlinenum();
    }
#endif
  }
}

/**************************************************************************
* LD_FUNC_BC
**************************************************************************/
void G__bc_inst::LD_FUNC_BC(struct G__ifunc_table* ifunc,int ifn,int paran,void* pfunc) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,
			      "%3x: LD_FUNC bytecode %s paran=%d\n"
			      ,G__asm_cp,ifunc->funcname[ifn],paran);
#endif
  G__asm_inst[G__asm_cp]=G__LD_FUNC;
  G__asm_inst[G__asm_cp+1]=(long)ifunc;
  G__asm_inst[G__asm_cp+2]= ifn;
  G__asm_inst[G__asm_cp+3]=paran;
  G__asm_inst[G__asm_cp+4]=(long)pfunc;
  inc_cp_asm(5,0);
}

/**************************************************************************
* LD_FUNC_VIRTUAL
**************************************************************************/
void G__bc_inst::LD_FUNC_VIRTUAL(struct G__ifunc_table* ifunc,int ifn,int paran,void* pfunc) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,
			      "%3x: LD_FUNC virtual %s paran=%d\n"
			      ,G__asm_cp,ifunc->funcname[ifn],paran);
#endif
  G__asm_inst[G__asm_cp]=G__LD_FUNC;
  G__asm_inst[G__asm_cp+1]=(long)ifunc->tagnum;
  G__asm_inst[G__asm_cp+2]=(ifunc->vtblindex[ifn]&0xffff)
                           +(ifunc->vtblbasetagnum[ifn]*0x10000);
  G__asm_inst[G__asm_cp+3]=paran;
  G__asm_inst[G__asm_cp+4]=(long)pfunc;
  inc_cp_asm(5,0);
}

/**************************************************************************
* RETURN
**************************************************************************/
void G__bc_inst::RETURN() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: RETURN\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__RETURN;
  inc_cp_asm(1,0);
}

/**************************************************************************
* CAST
**************************************************************************/
void G__bc_inst::CAST(int type,int tagnum,int typenum,int reftype) {
#ifdef G__ASM_DBG
  if(G__asm_dbg&&G__asm_noverflow) {
    G__fprinterr(G__serr,"%3x: CAST to %c\n",G__asm_cp,type);
  }
#endif
  G__asm_inst[G__asm_cp]=G__CAST;
  G__asm_inst[G__asm_cp+1]=type;
  G__asm_inst[G__asm_cp+2]=typenum;
  G__asm_inst[G__asm_cp+3]=tagnum;
  G__asm_inst[G__asm_cp+4]=reftype;
  inc_cp_asm(5,0);
}

/**************************************************************************
* CAST
**************************************************************************/
void G__bc_inst::CAST(G__TypeInfo& x) {
#ifdef G__ASM_DBG
  if(G__asm_dbg&&G__asm_noverflow) {
    G__fprinterr(G__serr,"%3x: CAST to %c\n",G__asm_cp,x.Type());
  }
#endif
  G__asm_inst[G__asm_cp]=G__CAST;
  G__asm_inst[G__asm_cp+1]=x.Type();
  G__asm_inst[G__asm_cp+2]=x.Typenum();
  G__asm_inst[G__asm_cp+3]=x.Tagnum();
  G__asm_inst[G__asm_cp+4]=x.Reftype();
  inc_cp_asm(5,0);
}

/**************************************************************************
* OP1
**************************************************************************/
void G__bc_inst::OP1(int opr) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) {
    if(isprint(opr)) 
      G__fprinterr(G__serr,"%3x: OP1  '%c' %d\n"
	      ,G__asm_cp,opr,opr);
    else
      G__fprinterr(G__serr,"%3x: OP1  %d\n"
	      ,G__asm_cp,opr);
  }
#endif
  G__asm_inst[G__asm_cp]=G__OP1;
  G__asm_inst[G__asm_cp+1]=opr;
  inc_cp_asm(2,0);
}

/**************************************************************************
* LETVVAL
**************************************************************************/
void G__bc_inst::LETVVAL() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: LETVVAL\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__LETVVAL;
  inc_cp_asm(1,0);
}

/**************************************************************************
* ADDSTROS
**************************************************************************/
void G__bc_inst::ADDSTROS(int os) {
#ifdef G__ASM_DBG
  if(G__asm_dbg)
    G__fprinterr(G__serr,"%3x: ADDSTROS %d (bc_inst 1)\n" ,G__asm_cp,os);
#endif
  G__asm_inst[G__asm_cp]=G__ADDSTROS;
  G__asm_inst[G__asm_cp+1]=os;
  inc_cp_asm(2,0);
}

/**************************************************************************
* LETPVAL
**************************************************************************/
void G__bc_inst::LETPVAL() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: LETPVAL\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__LETPVAL;
  inc_cp_asm(1,0);
}
 
/**************************************************************************
* TOPNTR
**************************************************************************/
void G__bc_inst::TOPNTR() {
#ifdef G__ASM_DBG
  G__fprinterr(G__serr,"%3x: TOPNTR\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__TOPNTR;
  inc_cp_asm(1,0);
}

/**************************************************************************
* NOT
**************************************************************************/
void G__bc_inst::NOT() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: NOT\n" ,G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__NOT;
  inc_cp_asm(1,0);
}

/**************************************************************************
* BOOL
**************************************************************************/
void G__bc_inst::BOOL() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: BOOL\n" ,G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__BOOL;
  inc_cp_asm(1,0);
}

/**************************************************************************
* ISDEFAULTPARA
**************************************************************************/
int G__bc_inst::ISDEFAULTPARA(int addr) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) {
    G__fprinterr(G__serr,"%3x: ISDEFAULTPARA %x\n",G__asm_cp,G__asm_cp+4);
  }
#endif
  G__asm_inst[G__asm_cp] = G__ISDEFAULTPARA;
  G__asm_inst[G__asm_cp+1] = addr;
  inc_cp_asm(2,0);
  return(G__asm_cp-1);
}

/**************************************************************************
* LD_VAR
**************************************************************************/
void G__bc_inst::LD_VAR(struct G__var_array* var, int ig15,int paran,int var_type) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: LD_VAR  %s index=%d paran=%d\n"
			 ,G__asm_cp,var->varnamebuf[ig15],ig15,paran);
#endif
  G__asm_inst[G__asm_cp]=G__LD_VAR;
  G__asm_inst[G__asm_cp+1]=ig15;
  G__asm_inst[G__asm_cp+2]=paran;
  G__asm_inst[G__asm_cp+3]=var_type;
  G__asm_inst[G__asm_cp+4]=(long)var;
  inc_cp_asm(5,0);
}

/**************************************************************************
* ST_VAR
**************************************************************************/
void G__bc_inst::ST_VAR(struct G__var_array* var,int ig15,int paran,int var_type) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: ST_VAR  %s index=%d paran=%d\n"
			 ,G__asm_cp,var->varnamebuf[ig15],ig15,paran);
#endif
  G__asm_inst[G__asm_cp]=G__ST_VAR;
  G__asm_inst[G__asm_cp+1]=ig15;
  G__asm_inst[G__asm_cp+2]=paran;
  G__asm_inst[G__asm_cp+3]=var_type;
  G__asm_inst[G__asm_cp+4]=(long)var;
  inc_cp_asm(5,0);
}

/**************************************************************************
* LD_MSTR
**************************************************************************/
void G__bc_inst::LD_MSTR(struct G__var_array* var,int ig15,int paran
			,int var_type) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: LD_MSTR  %s index=%d paran=%d\n"
			 ,G__asm_cp,var->varnamebuf[ig15],ig15,paran);
#endif
  G__asm_inst[G__asm_cp]=G__LD_MSTR;
  G__asm_inst[G__asm_cp+1]=ig15;
  G__asm_inst[G__asm_cp+2]=paran;
  G__asm_inst[G__asm_cp+3]=var_type;
  G__asm_inst[G__asm_cp+4]=(long)var;
  inc_cp_asm(5,0);
}

/**************************************************************************
* ST_MSTR
**************************************************************************/
void G__bc_inst::ST_MSTR(struct G__var_array* var,int ig15,int paran
			,int var_type) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: ST_MSTR  %s index=%d paran=%d\n"
			 ,G__asm_cp,var->varnamebuf[ig15],ig15,paran);
#endif
  G__asm_inst[G__asm_cp]=G__ST_MSTR;
  G__asm_inst[G__asm_cp+1]=ig15;
  G__asm_inst[G__asm_cp+2]=paran;
  G__asm_inst[G__asm_cp+3]=var_type;
  G__asm_inst[G__asm_cp+4]=(long)var;
  inc_cp_asm(5,0);
}

/**************************************************************************
* LD_LVAR
**************************************************************************/
void G__bc_inst::LD_LVAR(struct G__var_array* var,int ig15,int paran
			,int var_type) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: LD_LVAR  %s index=%d paran=%d\n"
			 ,G__asm_cp,var->varnamebuf[ig15],ig15,paran);
#endif
  G__asm_inst[G__asm_cp]=G__LD_LVAR;
  G__asm_inst[G__asm_cp+1]=ig15;
  G__asm_inst[G__asm_cp+2]=paran;
  G__asm_inst[G__asm_cp+3]=var_type;
  G__asm_inst[G__asm_cp+4]=(long)var;
  inc_cp_asm(5,0);
}

/**************************************************************************
* ST_LVAR
**************************************************************************/
void G__bc_inst::ST_LVAR(struct G__var_array* var,int ig15,int paran,int var_type) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: ST_LVAR  %s index=%d paran=%d\n"
			 ,G__asm_cp,var->varnamebuf[ig15],ig15,paran);
#endif
  G__asm_inst[G__asm_cp]=G__ST_LVAR;
  G__asm_inst[G__asm_cp+1]=ig15;
  G__asm_inst[G__asm_cp+2]=paran;
  G__asm_inst[G__asm_cp+3]=var_type;
  G__asm_inst[G__asm_cp+4]=(long)var;
  inc_cp_asm(5,0);
}

/**************************************************************************
* CMP2
**************************************************************************/
void G__bc_inst::CMP2(int operator2) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: CMP2  '%c'\n" ,G__asm_cp,operator2);
#endif
  G__asm_inst[G__asm_cp]=G__CMP2;
  G__asm_inst[G__asm_cp+1]=(long)operator2;
  inc_cp_asm(2,0);
}

/**************************************************************************
* PUSHSTROS
**************************************************************************/
void G__bc_inst::PUSHSTROS() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: PUSHSTROS\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp] = G__PUSHSTROS;
  inc_cp_asm(1,0);
}

/**************************************************************************
* SETSTROS
**************************************************************************/
void G__bc_inst::SETSTROS() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: SETSTROS\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp] = G__SETSTROS;
  inc_cp_asm(1,0);
}

/**************************************************************************
* POPSTROS
**************************************************************************/
void G__bc_inst::POPSTROS() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: POPSTROS\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp] = G__POPSTROS;
  inc_cp_asm(1,0);
}

/**************************************************************************
* SETTEMP
**************************************************************************/
void G__bc_inst::SETTEMP() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: SETTEMP\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp] = G__SETTEMP;
  inc_cp_asm(1,0);
}

/**************************************************************************
* FREETEMP
**************************************************************************/
void G__bc_inst::FREETEMP() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: FREETEMP\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp] = G__FREETEMP;
  inc_cp_asm(1,0);
}

/**************************************************************************
* GETRSVD  ????
**************************************************************************/
void G__bc_inst::GETRSVD(const char* item) {
#ifdef G__ASM_DBG
      if(G__asm_dbg) G__fprinterr(G__serr,"%3x: GETRSVD $%s\n" ,G__asm_cp,item);
#endif
      /* GETRSVD */
      G__asm_inst[G__asm_cp]=G__GETRSVD;
      G__asm_inst[G__asm_cp+1]=(long)((void*)item); // ???
      inc_cp_asm(1,0);            // ???
}

/**************************************************************************
* REWINDSTACK
**************************************************************************/
void G__bc_inst::REWINDSTACK(int rewind) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: REWINDSTACK %d\n"
			      ,G__asm_cp,rewind);
#endif
  G__asm_inst[G__asm_cp] = G__REWINDSTACK;
  G__asm_inst[G__asm_cp+1] = rewind;
  inc_cp_asm(2,0);
}

/**************************************************************************
* CND1JMP
**************************************************************************/
int G__bc_inst::CND1JMP(int addr) {
  int asm_jumppointer=0;
  if(addr) {
#ifdef G__ASM_DBG
    if(G__asm_dbg) G__fprinterr(G__serr,"%3x: CND1JMP %d to %x\n"
			       ,G__asm_cp
				,G__int(G__asm_stack[G__asm_dt-1])
			       ,G__asm_inst[G__asm_cp+1]);
#endif
    G__asm_inst[G__asm_cp]=G__CND1JMP;
    G__asm_inst[G__asm_cp+1]=addr;
    inc_cp_asm(2,0);
  }
  else {
#ifdef G__ASM_DBG
    if(G__asm_dbg) 
      G__fprinterr(G__serr,"%3x: CND1JMP assigned later\n",G__asm_cp);
#endif
    G__asm_inst[G__asm_cp]=G__CND1JMP;
    G__asm_inst[G__asm_cp+1]=0;
    asm_jumppointer = G__asm_cp+1;
    inc_cp_asm(2,0);
  }
  return(asm_jumppointer);
}

/**************************************************************************
* LD_IFUNC
**************************************************************************/
void G__bc_inst::LD_IFUNC(struct G__ifunc_table *p_ifunc,int ifn,int hash
		   ,int paran,int funcmatch,int memfunc_flag) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: LD_IFUNC %s paran=%d\n"
			      ,G__asm_cp,p_ifunc->funcname[ifn],paran);
#endif
  if(!hash) {
    int len;
    G__hash(p_ifunc->funcname[ifn],hash,len);
  }
  if(0 && p_ifunc->pentry[ifn]->bytecode  && 0==p_ifunc->isvirtual[ifn]  ){
    // TODO, this causes problem, maybe bytecode pointer is not initialized
    LD_FUNC((char*)(p_ifunc->pentry[ifn]->bytecode)
	    ,hash
	    ,paran
	    ,(void*)G__exec_bytecode);
  }
  else {
    G__asm_inst[G__asm_cp]=G__LD_IFUNC;
    G__asm_inst[G__asm_cp+1]=(long)p_ifunc->funcname[ifn];
    G__asm_inst[G__asm_cp+2]=hash;
    G__asm_inst[G__asm_cp+3]=paran;
    G__asm_inst[G__asm_cp+4]=(long)p_ifunc;
    G__asm_inst[G__asm_cp+5]=(long)funcmatch;
    G__asm_inst[G__asm_cp+6]=(long)memfunc_flag;
    G__asm_inst[G__asm_cp+7]=(long)ifn;
    inc_cp_asm(8,0);
  }
}

/**************************************************************************
* NEWALLOC
**************************************************************************/
void G__bc_inst::NEWALLOC(int size,int isclass_array) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: NEWALLOC %d %d\n",G__asm_cp,size,isclass_array);
#endif
  G__asm_inst[G__asm_cp] = G__NEWALLOC;
  G__asm_inst[G__asm_cp+1] = size;
  G__asm_inst[G__asm_cp+2] = isclass_array;
  inc_cp_asm(3,0);
}
/**************************************************************************
* SET_NEWALLOC
**************************************************************************/
void G__bc_inst::SET_NEWALLOC(int tagnum,int var_type) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: SET_NEWALLOC %d %c\n",G__asm_cp,tagnum,var_type);
#endif
  G__asm_inst[G__asm_cp] = G__SET_NEWALLOC;
  G__asm_inst[G__asm_cp+1] = tagnum;
  G__asm_inst[G__asm_cp+2] = toupper(var_type);
  inc_cp_asm(3,0);
}
/**************************************************************************
* SET_NEWALLOC
**************************************************************************/
void G__bc_inst::SET_NEWALLOC(const G__TypeInfo& type) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: SET_NEWALLOC %s\n",G__asm_cp
			      ,(char*)((G__TypeInfo)type).Name());
#endif
  G__asm_inst[G__asm_cp] = G__SET_NEWALLOC;
  G__asm_inst[G__asm_cp+1] = type.Tagnum();
  G__asm_inst[G__asm_cp+2] = type.Type()|(type.Reftype()<<8);
  inc_cp_asm(3,0);
}

/**************************************************************************
* DELETEFREE
**************************************************************************/
void G__bc_inst::DELETEFREE(int isarray) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: DELETEFREE  %d\n",G__asm_cp,isarray);
#endif
  G__asm_inst[G__asm_cp] = G__DELETEFREE;
  G__asm_inst[G__asm_cp+1] = isarray;
  inc_cp_asm(2,0);
}

/**************************************************************************
* SWAP
**************************************************************************/
void G__bc_inst::SWAP(int /* isarray */) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: SWAP\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp] = G__SWAP;
  inc_cp_asm(1,0);
}

/**************************************************************************
* BASECONV
**************************************************************************/
void G__bc_inst::BASECONV(int formal_tagnum,int baseoffset) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: BASECONV %d %d\n"
			      ,G__asm_cp,formal_tagnum,baseoffset);
#endif
  G__asm_inst[G__asm_cp] = G__BASECONV;
  G__asm_inst[G__asm_cp+1] = formal_tagnum;
  G__asm_inst[G__asm_cp+2] = baseoffset;
  inc_cp_asm(3,0);
}

/**************************************************************************
* STORETEMP
**************************************************************************/
void G__bc_inst::STORETEMP() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: STORETEMP\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__STORETEMP;
  inc_cp_asm(1,0);
}

/**************************************************************************
* ALLOCTEMP
**************************************************************************/
void G__bc_inst::ALLOCTEMP(int tagnum) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) 
      G__fprinterr(G__serr,"%3x: ALLOCTEMP %s %d\n"
		   ,G__asm_cp,G__struct.name[tagnum],tagnum);
#endif
  G__asm_inst[G__asm_cp] = G__ALLOCTEMP;
  G__asm_inst[G__asm_cp+1] = tagnum;
  inc_cp_asm(2,0);
}

/**************************************************************************
* POPTEMP
**************************************************************************/
void G__bc_inst::POPTEMP(int tagnum) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: POPTEMP %d\n",G__asm_cp,tagnum);
#endif
  G__asm_inst[G__asm_cp] = G__POPTEMP;
  G__asm_inst[G__asm_cp+1] = tagnum;
  inc_cp_asm(2,0);
}

/**************************************************************************
* REORDER
**************************************************************************/
void G__bc_inst::REORDER (int paran,int ig25) {
#ifdef G__ASM_DBG
  if(G__asm_dbg)
  G__fprinterr(G__serr,"%x: REORDER inserted before ST_VAR/MSTR/LD_VAR/MSTR\n"
	       ,G__asm_cp-5);
#endif
  for(int i=1;i<=5;i++) G__asm_inst[G__asm_cp-i+3]=G__asm_inst[G__asm_cp-i];
  G__asm_inst[G__asm_cp-5]= G__REORDER ;
  G__asm_inst[G__asm_cp-4]= paran ;
  G__asm_inst[G__asm_cp-3]= ig25 ;
  inc_cp_asm(3,0);
}

/**************************************************************************
* LD_THIS
**************************************************************************/
void G__bc_inst::LD_THIS(int var_type) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: LD_THIS %c\n",G__asm_cp,var_type);
#endif
  G__asm_inst[G__asm_cp] = G__LD_THIS;
  G__asm_inst[G__asm_cp+1] = var_type;
  inc_cp_asm(2,0);
}

/**************************************************************************
* RTN_FUNC
**************************************************************************/
void G__bc_inst::RTN_FUNC(int isreturn) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x : RTN_FUNC %d\n",G__asm_cp,isreturn);
#endif
  G__asm_inst[G__asm_cp] = G__RTN_FUNC;
  G__asm_inst[G__asm_cp+1] = isreturn;
  inc_cp_asm(2,0);
}

/**************************************************************************
* SETMEMFUNCENV
**************************************************************************/
void G__bc_inst::SETMEMFUNCENV() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: SETMEMFUNCENV\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__SETMEMFUNCENV;
  inc_cp_asm(1,0);
}

/**************************************************************************
* RECMEMFUNCENV
**************************************************************************/
void G__bc_inst::RECMEMFUNCENV() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: RECMEMFUNCENV\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__RECMEMFUNCENV;
  inc_cp_asm(1,0);
}

/**************************************************************************
* ADDALLOCTABLE
**************************************************************************/
void G__bc_inst::ADDALLOCTABLE() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: ADDALLOCTABLE\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__ADDALLOCTABLE;
  inc_cp_asm(1,0);
}

/**************************************************************************
* DELALLOCTABLE
**************************************************************************/
void G__bc_inst::DELALLOCTABLE() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: DELALLOCTABLE\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__DELALLOCTABLE;
  inc_cp_asm(1,0);
}

/**************************************************************************
* BASEDESTRUCT
**************************************************************************/
void G__bc_inst::BASEDESTRUCT(int tagnum,int isarray) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: BASEDESTRUCT %d %d\n"
			      ,G__asm_cp,tagnum,isarray);
#endif
  G__asm_inst[G__asm_cp] = G__BASEDESTRUCT;
  G__asm_inst[G__asm_cp+1] = tagnum;
  G__asm_inst[G__asm_cp+2] = isarray;
  inc_cp_asm(3,0);
}

/**************************************************************************
* REDECL ,  MUST NOT USE THIS INSTRUCTION
**************************************************************************/
void G__bc_inst::REDECL(struct G__var_array* var,int ig15) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: REDECL\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp] = G__REDECL;
  G__asm_inst[G__asm_cp+1]=ig15;
  G__asm_inst[G__asm_cp+2]=(long)var;
  inc_cp_asm(3,0);
}

/**************************************************************************
* TOVALUE
**************************************************************************/
void G__bc_inst::TOVALUE(G__value *pbuf) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: TOVALUE\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__TOVALUE;
  switch(pbuf->obj.reftype.reftype) {
  case G__PARANORMAL:
  case G__PARAREFERENCE:
    switch(pbuf->type) {
    case 'B': G__asm_inst[G__asm_cp+1]=(long)G__asm_tovalue_B; break;
    case 'C': G__asm_inst[G__asm_cp+1]=(long)G__asm_tovalue_C; break;
    case 'R': G__asm_inst[G__asm_cp+1]=(long)G__asm_tovalue_R; break;
    case 'S': G__asm_inst[G__asm_cp+1]=(long)G__asm_tovalue_S; break;
    case 'H': G__asm_inst[G__asm_cp+1]=(long)G__asm_tovalue_H; break;
    case 'I': G__asm_inst[G__asm_cp+1]=(long)G__asm_tovalue_I; break;
    case 'K': G__asm_inst[G__asm_cp+1]=(long)G__asm_tovalue_K; break;
    case 'L': G__asm_inst[G__asm_cp+1]=(long)G__asm_tovalue_L; break;
    case 'F': G__asm_inst[G__asm_cp+1]=(long)G__asm_tovalue_F; break;
    case 'D': G__asm_inst[G__asm_cp+1]=(long)G__asm_tovalue_D; break;
    case 'U': G__asm_inst[G__asm_cp+1]=(long)G__asm_tovalue_U; break;
    default: /* SHOULD NEVER HAPPEN */ break;
    }
    break;
  case G__PARAP2P:
    G__asm_inst[G__asm_cp+1]=(long)G__asm_tovalue_p2p;
    break;
  default:
    G__asm_inst[G__asm_cp+1]=(long)G__asm_tovalue_p2p2p2;
    break;
  }
  inc_cp_asm(2,0);
}

/**************************************************************************
* INIT_REF, TODO??? INIT_REF implementation in pcode.c is questionable -> review
**************************************************************************/
void G__bc_inst::INIT_REF(struct G__var_array* var,int ig15,int paran
			,int var_type) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: INIT_REF\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp] = G__INIT_REF;
  G__asm_inst[G__asm_cp+1]=ig15;
  G__asm_inst[G__asm_cp+2]=paran;     // paran may not be used
  G__asm_inst[G__asm_cp+3]=var_type;
  G__asm_inst[G__asm_cp+4]=(long)var;
  inc_cp_asm(5,0);
}

/**************************************************************************
* PUSHCPY
**************************************************************************/
void G__bc_inst::PUSHCPY() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: PUSHCPY\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp] = G__PUSHCPY;
  inc_cp_asm(1,0);
}

/**************************************************************************
* LETNEWVAL
**************************************************************************/
void G__bc_inst::LETNEWVAL() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: LETNEWVAL\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__LETNEWVAL;
  inc_cp_asm(1,0);
}

/**************************************************************************
* SETGVP
**************************************************************************/
void G__bc_inst::SETGVP(int pushpop) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: SETGVP %d''\n",G__asm_cp,pushpop);
#endif
  G__asm_inst[G__asm_cp]=G__SETGVP;
  G__asm_inst[G__asm_cp+1]=pushpop;
  inc_cp_asm(2,0);
}

/**************************************************************************
* TOPVALUE
**************************************************************************/
void G__bc_inst::TOPVALUE() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: TOPVALUE\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__TOPVALUE;
  inc_cp_asm(1,0);
}

/**************************************************************************
* CTOR_SETGVP 
**************************************************************************/
void G__bc_inst::CTOR_SETGVP(struct G__var_array* var,int ig15,int mode) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: CTOR_SETGVP %s\n"
			      ,G__asm_cp,var->varnamebuf[ig15]);
#endif
  G__asm_inst[G__asm_cp]=G__CTOR_SETGVP;
  G__asm_inst[G__asm_cp+1]=ig15;
  G__asm_inst[G__asm_cp+2]=(long)var;
  G__asm_inst[G__asm_cp+3]=(long)mode;
  inc_cp_asm(4,0);
}

/**************************************************************************
* TRY
**************************************************************************/
int G__bc_inst::TRY(int first_catchblock,int endof_catchblock) {
  int asm_jumppointer=0;
  G__asm_inst[G__asm_cp]=G__TRY;
  if(first_catchblock) {
#ifdef G__ASM_DBG
    if(G__asm_dbg) G__fprinterr(G__serr,"%3x: TRY %x %x\n",G__asm_cp
				,first_catchblock,endof_catchblock);
#endif
    G__asm_inst[G__asm_cp+1]=first_catchblock;
    G__asm_inst[G__asm_cp+2]=endof_catchblock;
  }
  else {
#ifdef G__ASM_DBG
    if(G__asm_dbg) G__fprinterr(G__serr,"%3x: TRY assigned later\n",G__asm_cp);
#endif
    G__asm_inst[G__asm_cp+1]=0;
    G__asm_inst[G__asm_cp+2]=0;
    asm_jumppointer = G__asm_cp+1;
  }
  inc_cp_asm(3,0);
  return(asm_jumppointer);
}

/**************************************************************************
* TYPEMATCH
**************************************************************************/
void G__bc_inst::TYPEMATCH(G__value *pval) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: TYPEMATCH\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__TYPEMATCH;
  G__asm_inst[G__asm_cp+1]=G__asm_dt;
  G__asm_stack[G__asm_dt] = *pval;
  inc_cp_asm(2,1);
}

/**************************************************************************
* ALLOCEXCEPTION
**************************************************************************/
void G__bc_inst::ALLOCEXCEPTION(int tagnum) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) 
    G__fprinterr(G__serr,"%3x: ALLOCEXCEPTION %d\n",G__asm_cp,tagnum);
#endif
  G__asm_inst[G__asm_cp]=G__ALLOCEXCEPTION;
  G__asm_inst[G__asm_cp+1]=tagnum;
  inc_cp_asm(2,0);
}

/**************************************************************************
* DESTROYEXCEPTION
**************************************************************************/
void G__bc_inst::DESTROYEXCEPTION() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: DESTROYEXCEPTION\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__DESTROYEXCEPTION;
  inc_cp_asm(1,0);
}

/**************************************************************************
* THROW
**************************************************************************/
void G__bc_inst::THROW() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: THROW\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__THROW;
  inc_cp_asm(1,0);
}

/**************************************************************************
* CATCH , NOT READY
**************************************************************************/
void G__bc_inst::CATCH() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: CATCH\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__CATCH;
  /* THIS INSTRUCTION IS NOT IMPLEMENTED */
  inc_cp_asm(5,0);
}

/**************************************************************************
* SETARYINDEX
**************************************************************************/
void G__bc_inst::SETARYINDEX(int newauto) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: SETARYINDEX\n",G__asm_cp,newauto);
#endif
  G__asm_inst[G__asm_cp]=G__SETARYINDEX;
  G__asm_inst[G__asm_cp+1]=newauto;
  inc_cp_asm(2,0);
}

/**************************************************************************
* RESETARYINDEX
**************************************************************************/
void G__bc_inst::RESETARYINDEX(int newauto) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: RESETARYINDEX\n",G__asm_cp,newauto);
#endif
  G__asm_inst[G__asm_cp]=G__RESETARYINDEX;
  G__asm_inst[G__asm_cp+1]=newauto;
  inc_cp_asm(2,0);
}

/**************************************************************************
* GETARYINDEX
**************************************************************************/
void G__bc_inst::GETARYINDEX() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: GETARYINDEX\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__GETARYINDEX;
  inc_cp_asm(1,0);
}

/**************************************************************************
* PAUSE
**************************************************************************/
void G__bc_inst::PAUSE() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: PAUSE\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__PAUSE;
  inc_cp_asm(1,0);
}
/**************************************************************************
* NOP
**************************************************************************/
void G__bc_inst::NOP() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: NOP\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__NOP;
  inc_cp_asm(1,0);
}

/**************************************************************************
* ENTERSCOPE
**************************************************************************/
void G__bc_inst::ENTERSCOPE() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: ENTERSCOPE\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__ENTERSCOPE;
  inc_cp_asm(1,0);
}

/**************************************************************************
* EXITSCOPE
**************************************************************************/
void G__bc_inst::EXITSCOPE() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: EXITSCOPE\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__EXITSCOPE;
  inc_cp_asm(1,0);
}

/**************************************************************************
* PUTAUTOOBJ
**************************************************************************/
void G__bc_inst::PUTAUTOOBJ(struct G__var_array* var,int ig15) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: PUTAUTOOBJ\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__PUTAUTOOBJ;
  G__asm_inst[G__asm_cp+1]=(long)var;
  G__asm_inst[G__asm_cp+2]=(long)ig15;
  inc_cp_asm(3,0);
}

/**************************************************************************
* CASE
**************************************************************************/
void G__bc_inst::CASE(void* x) {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: CASE\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__CASE;
  G__asm_inst[G__asm_cp+1]=(long)x;
  inc_cp_asm(2,0);
}


/**************************************************************************
* MEMCPY
**************************************************************************/
void G__bc_inst::MEMCPY() {
#ifdef G__ASM_DBG
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: MEMCPY\n",G__asm_cp);
#endif
  G__asm_inst[G__asm_cp]=G__MEMCPY;
  inc_cp_asm(1,0);
}

/**************************************************************************
* MEMSETINT
**************************************************************************/
void G__bc_inst::MEMSETINT(int mode,map<long,long>& x) {
  if(0==x.size()) return;
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: MEMSETINT\n",G__asm_cp);
  G__asm_inst[G__asm_cp]=G__MEMSETINT;
  G__asm_inst[G__asm_cp+1]=mode; //0:0, 1:G__store_struct_offset, 2:localmem
  G__asm_inst[G__asm_cp+2]=x.size();
  inc_cp_asm(3,0);
  for(map<long,long>::iterator i=x.begin();i!=x.end();++i) {
    G__asm_inst[G__asm_cp]   = (*i).first;
    G__asm_inst[G__asm_cp+1] = (*i).second;
    inc_cp_asm(2,0);
  }
}

/**************************************************************************
* JMPIFVIRTUALOBJ
**************************************************************************/
int G__bc_inst::JMPIFVIRTUALOBJ(int offset,int addr) {
  if(G__asm_dbg) G__fprinterr(G__serr,"%3x: JMPIFVIRTUALOBJ\n",G__asm_cp);
  G__asm_inst[G__asm_cp]=G__JMPIFVIRTUALOBJ;
  G__asm_inst[G__asm_cp+1]=offset;
  G__asm_inst[G__asm_cp+2]=addr;
  int asm_jumppointer=G__asm_cp+2;
  inc_cp_asm(3,0);
  return(asm_jumppointer);
}

/**************************************************************************
* VIRTUALADDSTROS
**************************************************************************/
void G__bc_inst::VIRTUALADDSTROS(int tagnum,struct G__inheritance* baseclass
				 ,int basen) {
  if(G__asm_cp>4 && G__asm_inst[G__asm_cp-4]==G__VIRTUALADDSTROS) 
    inc_cp_asm(-4,0);
  else 
    if(G__asm_dbg) G__fprinterr(G__serr,"%3x: VIRTUALADDSTROS\n",G__asm_cp);
  G__asm_inst[G__asm_cp]=G__VIRTUALADDSTROS;
  G__asm_inst[G__asm_cp+1]=tagnum;
  G__asm_inst[G__asm_cp+2]=(long)baseclass;
  G__asm_inst[G__asm_cp+3]=basen;
  inc_cp_asm(4,0);
}

/**************************************************************************
* cancel_VIRTUALADDSTROS
**************************************************************************/
void G__bc_inst::cancel_VIRTUALADDSTROS() {
  if(G__asm_cp>4 && G__asm_inst[G__asm_cp-4]==G__VIRTUALADDSTROS) {
    inc_cp_asm(-4,0);
    if(G__asm_dbg) G__fprinterr(G__serr,"VIRTUALADDSTROS cancelled\n");
  }
}

////////////////////////////////////////////////////////////////////////////

/*
 * Local Variables:
 * c-tab-always-indent:nil
 * c-indent-level:2
 * c-continued-statement-offset:2
 * c-brace-offset:-2
 * c-brace-imaginary-offset:0
 * c-argdecl-indent:0
 * c-label-offset:-2
 * compile-command:"make -k"
 * End:
 */

